/*
 * randomtestadventuer.c
 * Assignment 4: Random tester
 *  Created on: Feb 6, 2014
 *  Help: I ran into issues getting my state to a refresh after
 *  so many runs and so I saw during a code review that my
 *  project partner had used a set of functions with one to
 *  refresh (or set) state. I credit him for this and I will
 *  be adopting this concept from this point forward.
 *  I do not recall the exact version I saw the code in but the last
 *  version of it is located at
 *  https://code.google.com/p/cs362-winter2014/source/browse/trunk/todtm/Dominion/testhelpers.c
 *      Author: Charles Clampitt
 */

#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "rngs.h"
#include <math.h>

#define DEBUG 0

// Prototype
int adventurerTest(int player, int card, int handPos, int choice1, int choice2, int choice3, struct gameState *state);
void setState(struct gameState *state);
int *randomCard(struct gameState *state);
void setHand(struct gameState *state);
void setDeck(struct gameState *state);
int countTreasure(struct gameState *state);


void setState(struct gameState *state){
  int i;
  state->numPlayers = 4;
  for (i = adventurer; i <= treasure_map; i++){
    state->supplyCount[i] = 10;
    state->embargoTokens[i] = 0;
  }
  state->playedCardCount = 0;
  state->outpostPlayed = 0;
  state->outpostTurn = 0;
  state->whoseTurn = 0;
  state->coins = 0;
  state->phase = 0;
  state->numActions = 1; // we always have one action to start
   state->numBuys = 1; // always start with one buy
  for (i = 0; i< state->numPlayers; i++){
    state->handCount[i] = 0;
    state->deckCount[i] = 0;
    state->discardCount[i] = 0;
  }

}

// picks a random card to generate
int *randomCard(struct gameState *state){
    int random;
    int card;
    card = floor((Random() * 23)) + 1;

    switch(card){
        case 1:
            random = adventurer;
            break;
        case 2:
            random = council_room;
            break;
        case 3:
            random = feast;
            break;
        case 4:
            random = gardens;
            break;
        case 5:
            random = mine;
            break;
        case 6:
            random = remodel;
            break;
        case 7:
            random = smithy;
            break;
        case 8:
            random = village;
            break;
        case 9:
            random = baron;
            break;
        case 10:
            random = great_hall;
            break;
        case 11:
            random = minion;
            break;
        case 12:
            random = steward;
            break;
        case 13:
            random = tribute;
            break;
        case 14:
            random = ambassador;
            break;
        case 15:
            random = cutpurse;
            break;
        case 16:
            random = embargo;
            break;
        case 17:
            random = outpost;
            break;
        case 18:
            random = salvager;
            break;
        case 19:
            random = sea_hag;
            break;
        case 20:
            random = treasure_map;
            break;
        case 21:
        	random = gold;
        	break;
        case 22:
        	random = silver;
        	break;
        case 23:
        	random = copper;
        	break;
        case 24:
            random = *randomCard(state);
            break;
    }

        return (int*)random;
}


int countTreasure(struct gameState *state){
    int i;
    int treasure = 0;
    for(i = 0; i < state->deckCount[0]; i++){
        if (state->deck[0][i]== gold || state->deck[0][i] == silver || state->deck[0][i] == copper){
        	treasure++;
        }
        if (treasure > 2){
            return 0;
        }
    }
    return 1;
}

void setHand(struct gameState *state)
{
    int i;
    state->handCount[0] = 0;
    // Set our hand count to 5 starting
    for (i = 0; i < 5; i++){
        state->hand[0][i] = (int)*randomCard;
        state->handCount[0]++;
    }
    // And lastly always put the adventurer card in the hand somewhere
    int pos = floor((Random() * 4)) + 1;
    state->hand[0][pos] = adventurer;
}

void setDeck(struct gameState *state){
    int i;
    state->deckCount[0] = 0;
    for (i = 0; i < 50; i++){
        state->deck[0][i] = (int)*randomCard;
        state->deckCount[0]++;
    }
    state->deck[0][25] = copper;
    state->deck[0][30] = silver;
    state->deck[0][35] = gold;
}


/*
 * This test will take the current playe, handPos, and passed randomly the choice of 1-3 and the game state.
 * At some point I may want to make this match the cardeffect method signature a bit better by adding the
 * bonus parameter as well so I can use this as a template for all card tests.
 */
int adventurerTest(int player, int card, int handPos, int choice1, int choice2, int choice3, struct gameState *state)
{

  int numerrors = 0;
  int testcount = 0;


	   if (countTreasure(state) == 1){
	           // Skip test because not enough treasure
	        }
	         else {


	  	  	  // Get our test count for the player and hand
	   	  	  testcount = state->handCount[0];

	   	  	  // call the cardeffect and see what the new count will be
	   	  	  // This will be the expected that we compare after the below test and it should equal result
	   	  	  //expected = cardEffect(card, choice1, choice2, choice3, state, handPos, 0);
	               cardEffect(adventurer, 0, 0, 0, state, 0, 0);

	               // Show me the card drawn
	           //    cardDrawn = gsPre->hand[players][gsPre->handCount[players]-1];//top card of hand is most recently drawn card.
	             //         printf("cardDrawn was %d\n", cardDrawn);

	               // draw 2 discard 1 = +1  -- This is hand count
	               if (state->handCount[0] != testcount + 1)
	               {
	                	  numerrors = numerrors + 1;//did not match so add to error count
	             	  printf("Our current hand count is %d when it should be %d\n", state->handCount[0], testcount+1);
	               }


	               // Check that we should have 2 treasure cards
	               int bob;
	               for(bob=1; bob<3;  bob++)
	               {
	            	   if (state->hand[0][state->handCount[0]-bob] != copper && state->hand[0][state->handCount[0]-bob] != silver && state->hand[0][state->handCount[0]-bob] != gold)
	            	  	               {
	            	  	                   printf("Card %d drawn and left in deck should have been treasure and was not\n", bob);
	            	  	                   numerrors = numerrors + 1;//did not draw treasure

	            	  	               }
	               }

	               // Check that the last card that the player played was the adventurer card
	               // Because as we can see from the code for adventurer the code does not call
	               //  discardCard(handPos, currentPlayer, state, 0);
	               if (state->playedCards[0] != adventurer)
	               {
	            	   // the last card played was not the adventurer so add to error count
	             	  numerrors = numerrors + 1;
	                   printf("The card played was %d, but should have been %d\n", state->playedCards[0], adventurer);
	               }

  }


  	  	  	   setDeck(state);
 	           setHand(state);
 	          state->hand[0][state->handCount[0]] = -1;
 	         state->hand[0][state->handCount[0] + 1] = -1;


  // Return 0 if no errors otherwise return numerrors count
  return numerrors;
}



int main(){

	int x;
	int testNums = 5000; // number of tests to run
	int players;
	int numErrors = 0; // counter for number of errors found
	int handPos, card, choice1, choice2, choice3;
	struct gameState *gsPre = malloc(sizeof(struct gameState));

	setState(gsPre);
	setDeck(gsPre);
	setHand(gsPre);


  printf("Testing adventurer start\n");

  for (x = 0; x < testNums; x++) {

    numErrors += adventurerTest(players, card, handPos, choice1, choice2, choice3, gsPre);

    // After each run we need to reset everything otherwise the
    // whole thing crashes after a few hundred or so tests.
    setState(gsPre);
    setDeck(gsPre);
   	setHand(gsPre);
   	gsPre->hand[0][gsPre->handCount[0]] = -1;
   	gsPre->hand[0][gsPre->handCount[0] + 1] = -1;

  }

  printf ("ALL TESTS RUN!\n");

  free(gsPre);

  if (numErrors == 0){ printf("There were no errors found in this tests!\n");  }
  else if(numErrors > 0){ printf("There were %d errors in the tests run!\n",numErrors); }
  else{ printf("The error count was not 0 or more so your test puked! \n");  }

  return 0;

}

